package com.wan37.logic.fighting.auto.impl;

import com.wan37.logic.component.LogicWorkerHandlerCenter;
import com.wan37.logic.component.Worker;
import com.wan37.logic.handler.server.SuperMoveHandler;
import com.wan37.logic.utils.DelayDequeThreadPollUtil;
import com.wan37.logic.utils.RouteUtils;
import com.wan37.protobuf.constant.*;
import com.wan37.logic.domain.Result;
import com.wan37.logic.domain.vo.*;
import com.wan37.logic.fighting.SkillDelayThreadPool;
import com.wan37.logic.fighting.auto.AutoFighting;
import com.wan37.logic.fighting.auto.AutoSkillServiceManager;
import com.wan37.logic.fighting.hand.Fighting;
import com.wan37.logic.global.reference.SpringContextHolder;
import com.wan37.logic.handler.WorkerHandler;
import com.wan37.logic.service.cache.RoleServiceCache;
import com.wan37.logic.service.cache.SceneServiceCache;
import com.wan37.logic.service.cache.UserServiceCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * @author : luoyong
 * @date : 2020-07-08 16:29
 **/
@Component("autoPlayerService")
public class AutoPlayerServiceImpl implements AutoFighting {
    private final static Logger logger = LoggerFactory.getLogger(AutoPlayerServiceImpl.class);
    @Autowired
    private LogicWorkerHandlerCenter logicWorkerHandlerCenter;
    @Autowired
    private UserServiceCache userServiceCache;
    @Autowired
    private AutoSkillServiceManager autoSkillServiceManager;
    @Autowired
    private SkillDelayThreadPool skillDelayThreadPool;
    @Autowired
    private RoleServiceCache roleServiceCache;
    @Autowired
    private SceneServiceCache sceneServiceCache;
    @Autowired
    private DelayDequeThreadPollUtil delayDequeThreadPollUtil;
    @Autowired
    private RouteUtils routeUtils;

    /**
     * 角色对应是否战斗线程池，方便停止战斗
     */
    public static Map<String, ThreadPoolExecutor> allRoleIdToExecutor = new ConcurrentHashMap<>();

    @Override
    public void fighting(String sceneId, String fightingId) {
        userServiceCache.getUserServiceMap().get(fightingId).getRoleIdList().forEach(roleId -> {
            autoSkillServiceManager.addAllRoleIdToPBQMap(roleId);
            roleServiceCache.getRoleServiceMap().get(roleId).getSkillVOMap().forEach(((s, skillVO) -> {
                skillDelayThreadPool.initAdd(skillVO.getUsage(), skillVO);
            }));
        });
        /**
         *boss战斗场景,pk对象为boss
         */
        if (sceneServiceCache.getSceneServiceMap().get(sceneId).getLabel() == 1) {
            List<AllRoleVO> allRoleVOList = sceneServiceCache.getSceneServiceMap()
                    .get(sceneId).getAllRoleVOMap().values().stream().filter(allRoleVO ->
                            allRoleVO.getLabel() == AllRoleLabel.MONSTER && allRoleVO.getStatus() != 1).collect(Collectors.toList());
            Fighting fighting = SpringContextHolder.getBean("playerAttackMonster");
            delayDequeThreadPollUtil.updateTimeSchedule(0, "", sceneId, new AutoPlayer(sceneId, fightingId, allRoleVOList, fighting));
        }
        /**
         * 竞技场战斗场景，pk对象为角色
         */
        else if (sceneServiceCache.getSceneServiceMap().get(sceneId).getLabel() == 2) {

        }
    }

    class AutoPlayer implements WorkerHandler {
        /**
         * 用户id
         */
        private String fightingId;
        private String sceneId;
        private Fighting fighting;
        List<AllRoleVO> allRoleVOList;

        public AutoPlayer() {
        }

        public AutoPlayer(String sceneId, String fightingId, List<AllRoleVO> allRoleVOList, Fighting fighting) {
            this.fightingId = fightingId;
            this.sceneId = sceneId;
            this.allRoleVOList = allRoleVOList;
            this.fighting = fighting;
        }

        @Override
        public void execute(Worker worker) throws Exception {
            List<String> allRoleVOIdList = new ArrayList<>();
            allRoleVOList.forEach(allRoleVO -> allRoleVOIdList.add(allRoleVO.getAllRoleId()));
            List<String> roleIdList = userServiceCache.getUserServiceMap().get(fightingId).getRoleIdList();
            roleIdList.forEach(roleId -> {
                RoleVO roleVO = roleServiceCache.getRoleServiceMap().get(roleId).getRoleVO();
                switch (roleVO.getStatus()) {
                    case 0:
                        SkillVO skillVO = autoSkillServiceManager.getPbqSkill(roleId);
                        if (skillVO != null) {
                            if (roleVO.getNumberMap().get(CommonBase.HP) - skillVO.getCostHP() < 0) {
                                logger.info(roleVO.getName() + " 使用 " +
                                        skillVO.getName() + " 技能失败，HP不够 ");
                                skillDelayThreadPool.add(roleId, skillVO, 2);
                                delayDequeThreadPollUtil.updateTimeSchedule(2, "", sceneId, new AutoPlayer(sceneId, fightingId, allRoleVOList, fighting));
                            } else if (roleVO.getNumberMap().get(CommonBase.MP) <= 0) {
                                logger.info(roleVO.getName() + " 使用 " +
                                        skillVO.getName() + " 技能失败，你已经死了！ ");
                                routeUtils.sendAttackBroadcastResponse(CommonFighting.ATTACK_ERROR_SELF_DIE, sceneServiceCache.getSceneServiceMap()
                                        .get(sceneId).getUserIdSet(), roleId, null, skillVO.getId(), null);
                            } else {
                                Result result = null;
                                if (skillVO.getLabel().startsWith(SkillLabel.AOE)
                                        && skillVO.getLabel().startsWith(SkillLabel.ENEMY)) {
                                    result = this.fighting.start(new FightingVO(skillVO.getId(),
                                            roleVO.getUserId(), roleId, allRoleVOIdList, sceneId));
                                } else if (skillVO.getLabel().startsWith(SkillLabel.AOE)
                                        && skillVO.getLabel().startsWith(SkillLabel.FRIEND)) {
                                    result = this.fighting.start(new FightingVO(skillVO.getId(),
                                            roleVO.getUserId(), roleId, roleIdList, sceneId));
                                } else if (skillVO.getLabel().startsWith(SkillLabel.ONE)
                                        && skillVO.getLabel().startsWith(SkillLabel.ENEMY)) {
                                    for (AllRoleVO allRoleVO : allRoleVOList) {
                                        if (allRoleVO.getStatus() == 0) {
                                            List<String> allRoleVOIdList1 = new ArrayList<>();
                                            allRoleVOIdList1.add(allRoleVO.getAllRoleId());
                                            result = this.fighting.start(new FightingVO(skillVO.getId(),
                                                    roleVO.getUserId(), roleId, allRoleVOIdList1, sceneId));
                                        }
                                    }
                                } else if (skillVO.getLabel().startsWith(SkillLabel.ONE)
                                        && skillVO.getLabel().startsWith(SkillLabel.FRIEND)) {

                                }
                                if (result instanceof SuccessFightingResult) {
                                    //技能处理完毕，将技能在CD时间后重新放回优先级技能队列
                                    skillDelayThreadPool.add(roleId, skillVO);
                                    SuccessFightingResult successFightingResult = (SuccessFightingResult) result;
                                    Map<String, Map<String, Long>> allRoleVONumberMap = successFightingResult.getAllRoleVONumberMap();
                                    /**
                                     * 发送释放技能改变状态广播消息
                                     */
                                    routeUtils.sendAttackBroadcastResponse(successFightingResult.getCode(), sceneServiceCache.getSceneServiceMap()
                                            .get(sceneId).getUserIdSet(), roleId, allRoleVOIdList, skillVO.getId(), allRoleVONumberMap);
                                }
                                int code = result.getCode();
                                if (code == CommonFighting.ATTACK_ERROR_BOSS_DIE) {
                                    routeUtils.sendAttackBroadcastResponse(code, sceneServiceCache.getSceneServiceMap()
                                            .get(sceneId).getUserIdSet(), roleId, null, skillVO.getId(), null);


                                    /**
                                     * 处理10s之后用户没有手动返回强制返回
                                     */
                                    String nextSceneId = sceneServiceCache.getSceneServiceMap().get(sceneId).getPreSceneId();
                                    delayDequeThreadPollUtil.updateTimeSchedule(10, roleId, sceneId, new SuperMoveHandler(sceneId, nextSceneId, fightingId,
                                            sceneServiceCache.getSceneServiceMap().get(sceneId).getSceneDO().getName()));
                                }
//                        clientHandler.sendAttackMessage(allRole.getAllRoleId(), monster.getAllRoleId(), skill.getId());
//                        logger.info(roleId + " 使用 " +
//                                skillVO.getName() + " 技能攻击了 " + monster.getAllRoleId());
                            }
                        } else {
                            delayDequeThreadPollUtil.updateTimeSchedule(1, "", sceneId, new AutoPlayer(sceneId, fightingId, allRoleVOList, fighting));
                        }
                        break;
                    case 1:
                        //角色死亡
                        break;
                    case 2:
                        //角色眩晕状态？
                        break;
                    default:
                        break;
                }
            });
        }
    }
}
